﻿namespace breakoutsharp.visual.gameobject
{
	using System;
	using System.Drawing;
	using Microsoft.DirectX;
	using Microsoft.DirectX.Direct3D;
	using System.Collections.Generic;
	public class Block : IScreenObject, IBlock, IDisposable
	{
		public enum BlockType : byte
		{
			Normal = 0x1,
			Indestructable = 0x2,
			Forged = 0x4,
			Robust = 0x8,
			PhaseShifter = 0x10,
			Rogue = 0x20
		}

		protected PointF location;
		protected SizeF size;
		protected bool dead = false;
		protected Color color = Color.Black;
		protected bool collidable = true;
		protected BlockType blockType = BlockType.Normal;
		protected int lives = 1;
		protected bool visible;

		protected static VertexBuffer blockVertex;
		protected static CustomVertex.PositionColored[] blockVertices;
		protected static CustomVertex.PositionTextured[] blockTexturedVertices;
		protected static Texture normalTexture;
		protected static Texture rogueTexture;
		protected static Texture phaseShifterTexture;
		protected static Texture phaseShifterOutTexture;
		protected static Texture robustTexture;
		protected static Texture robustCrackingTexture;
		protected static Texture forgedTexture;
		protected static Texture IndestructableTexture;

		private void CreateVertices(Device device)
		{
			/* Following was to be used if textures was wanted instead of plain colouring */
			CustomVertex.PositionTextured[] verts = new CustomVertex.PositionTextured[6];
			verts[0] = new CustomVertex.PositionTextured(new Vector3(0, 0, 0), 0, 0);
			verts[1] = new CustomVertex.PositionTextured(new Vector3(0, -15, 0), 0, 1);
			verts[2] = new CustomVertex.PositionTextured(new Vector3(60, 0, 0), 1, 0);
			verts[3] = new CustomVertex.PositionTextured(new Vector3(0, -15, 0), 0, 1);
			verts[4] = new CustomVertex.PositionTextured(new Vector3(60, -15, 0), 1, 1);
			verts[5] = new CustomVertex.PositionTextured(new Vector3(60, 0, 0), 1, 0);



			Block.blockVertex = new VertexBuffer(typeof(CustomVertex.PositionTextured), verts.Length, device, Usage.WriteOnly | Usage.Dynamic, CustomVertex.PositionTextured.Format, Pool.Default);
			Block.blockVertex.SetData(verts, 0, LockFlags.None);

			/* SAVE VERTICES FOR POTENTIAL LATER USE */
			Block.blockTexturedVertices = verts;

			/* Load block textures */
			normalTexture = new Texture(device, new Bitmap(@"data\gfx\block\brickNormal.jpg"), 0, Pool.Managed);
			rogueTexture = new Texture(device, new Bitmap(@"data\gfx\block\brickRogue.jpg"), 0, Pool.Managed);
			phaseShifterTexture = new Texture(device, new Bitmap(@"data\gfx\block\brickPhaseshifter.jpg"), 0, Pool.Managed);
			phaseShifterOutTexture = new Texture(device, new Bitmap(@"data\gfx\block\brick.jpg"), 0, Pool.Managed);
			robustTexture = new Texture(device, new Bitmap(@"data\gfx\block\brick.jpg"), 0, Pool.Managed);
			robustCrackingTexture = new Texture(device, new Bitmap(@"data\gfx\block\brickCrushed.jpg"), 0, Pool.Managed);
			forgedTexture = new Texture(device, new Bitmap(@"data\gfx\block\brickForged.jpg"), 0, Pool.Managed);
			IndestructableTexture = new Texture(device, new Bitmap(@"data\gfx\block\brickIndestructable.jpg"), 0, Pool.Managed);
		}

		public Block(BlockType bt)
		{
			blockType = bt;
			size = new SizeF(60, 15);

			switch (blockType)
			{
			case BlockType.Normal:
				color = Color.Orange;
				break;
			case BlockType.Indestructable:
				color = Color.Black;
				break;
			case BlockType.Forged:
				color = Color.Red;
				break;
			case BlockType.Robust:
				color = Color.Brown;
				this.lives = 2;
				break;
			case BlockType.PhaseShifter:
				color = Color.DeepSkyBlue;
				break;
			case BlockType.Rogue:
				color = Color.Green;
				break;
			default:
				color = Color.Beige;
				break;
			}
		}

		#region IScreenObject Members

		public void Draw(Device device)
		{
			if (Block.blockVertex == null)
			{
				CreateVertices(device);
			}

			// -- Draw blocks
			device.Transform.World = Matrix.Translation(this.Location.X, -1 * this.Location.Y, 0);

			device.SetStreamSource(0, Block.blockVertex, 0);

			Texture currentTexture;
			switch (blockType)
			{
			case BlockType.Normal:
				currentTexture = normalTexture;
				break;
			case BlockType.Indestructable:
				currentTexture = IndestructableTexture;
				break;
			case BlockType.Forged:
				currentTexture = forgedTexture;
				break;
			case BlockType.Robust:
				if (this.lives >= 2)
					currentTexture = robustTexture;
				else
					currentTexture = robustCrackingTexture;
				break;
			case BlockType.PhaseShifter:
				if (this.collidable)
					currentTexture = phaseShifterTexture;
				else
					currentTexture = phaseShifterOutTexture;
				break;
			case BlockType.Rogue:
				currentTexture = rogueTexture;
				break;
			default:
				currentTexture = normalTexture;
				break;
			}

			device.SetTexture(0, currentTexture);
			device.DrawPrimitives(PrimitiveType.TriangleList, 0, 2);
		}

		public PointF Location
		{
			get
			{
				return location;
			}
			set
			{
				location = value;
			}
		}

		public SizeF Size
		{
			get
			{
				return size;
			}
			set
			{
				size = value;
			}
		}

		public bool Visible
		{
			get
			{
				return visible;
			}
			set
			{
				visible = value;
			}
		}

		public Rectangle GetRect
		{
			get
			{
				return new Rectangle((int)this.Location.X, (int)location.Y, (int)size.Width, (int)size.Height);
			}
		}

		public RectangleF GetRectF
		{
			get
			{
				return new RectangleF(this.Location.X, location.Y, size.Width, size.Height);
			}
		}

		#endregion

		#region IBlock Members

		public bool Collidable
		{
			get
			{
				return collidable;
			}
			set
			{
				collidable = value;
			}
		}

		public Color Color
		{
			get
			{
				return color;
			}
			set
			{
				color = value;
			}
		}

		public bool Dead
		{
			get
			{
				return dead;
			}
			set
			{
				dead = value;
			}
		}

		public BlockType Type
		{
			get
			{
				return blockType;
			}
			set
			{
				blockType = value;
			}
		}

		public void BallHit(Ball b)
		{
			switch (blockType)
			{
			case BlockType.Normal:
			case BlockType.Rogue:
			case BlockType.PhaseShifter:
				if (collidable)
				{
					this.dead = true;
				}

				break;
			case BlockType.Indestructable:
				return;

			case BlockType.Robust:
				lives -= 1;
				if (lives == 0)
				{
					this.dead = true;
				}

				break;
			case BlockType.Forged:
				return;
			}
		}

		public void Update()
		{
			switch (blockType)
			{
			case BlockType.Normal:
				break;
			case BlockType.Indestructable:
				break;
			case BlockType.Forged:
				break;
			case BlockType.Robust:
				break;
			case BlockType.PhaseShifter:
				break;
			case BlockType.Rogue:
				break;
			default:
				break;
			}
		}

		#endregion

		public void Dispose()
		{
			throw new NotImplementedException();
		}
	}
}
